package com.overkill.game;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class RenderView extends SurfaceView implements SurfaceHolder.Callback {
	public static final String TYPEFACE_PATH = "fonts/celestiaredux.ttf";
	public static final boolean SHOW_DEBUG_INFO = false;

	private GameEngine engine = null;	

	private SurfaceHolder surfaceHolder;
	private Rect stage = null;
	private RenderThread renderThread;
	
	public boolean initialized = false;

	public boolean isSurfaceCreated = false;
	
	public RenderView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.surfaceHolder = getHolder();
		this.surfaceHolder.addCallback(this);
	}

	public RenderView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.surfaceHolder = getHolder();
		this.surfaceHolder.addCallback(this);
	}

	public RenderView(Context context) {
		super(context);
		this.surfaceHolder = getHolder();
		this.surfaceHolder.addCallback(this);
	}

	public void initialize(int targetFps) {
		this.renderThread = new RenderThread(this, targetFps);

		// Set size of your gameView
		this.stage = surfaceHolder.getSurfaceFrame();
		
		this.engine.inizialize(stage);
		
		this.initialized = true;
	}
	
	public void start(){
		this.renderThread.startRender();
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if(initialized == true){
			return;
		}
		this.initialize(this.engine.getTargetFps());
		this.start();
		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		if (this.initialized == false && engine.gameRunning == false) {
			boolean retry = true;
			this.renderThread.stopRender();
			while (retry) {
				try {
					this.renderThread.join();
					retry = false;
				} catch (InterruptedException e) {
					// we will try it again and again...
				}
			}
			this.initialized = false;
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	public void destroy() {
		this.initialized = false;
	}

	public void render(long gameTime, int deltaTime) {
		Canvas c = null;
		try {
			c = surfaceHolder.lockCanvas(null);
			synchronized (surfaceHolder) {
				this.update(gameTime, deltaTime);
				this.drawFrame(c);
			}
		} finally {
			if (c != null) {
				surfaceHolder.unlockCanvasAndPost(c);
			}
		}
	}

	private void update(long gameTime, int deltaTime) {
		this.engine.update(gameTime, deltaTime);
	}

	public void drawFrame() {
		Canvas c = null;
		try {
			c = surfaceHolder.lockCanvas(null);
			synchronized (surfaceHolder) {
				this.drawFrame(c);
			}
		} finally {
			if (c != null) {
				surfaceHolder.unlockCanvasAndPost(c);
			}
		}
	}

	protected void drawFrame(Canvas canvas) {
		if(this.initialized == false) return;
		engine.draw(canvas);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// Can't interact if not initialized
		if(this.initialized == false) return super.onTouchEvent(event);
		int action = event.getAction();
		int actionCode = action & MotionEvent.ACTION_MASK;
		if(actionCode == MotionEvent.ACTION_POINTER_DOWN){
			actionCode = MotionEvent.ACTION_DOWN;
		}
		if(actionCode == MotionEvent.ACTION_POINTER_UP){
			actionCode = MotionEvent.ACTION_UP;
		}
		int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
		engine.handleTouchEvent(actionCode, event.getX(pointerIndex), event.getY(pointerIndex));
		return true;		
	}

	public void setEngine(GameEngine engine) {
		this.engine = engine;
		this.engine.setContext(getContext());
		this.engine.setRenderView(this);
	}

	public GameEngine getEngine() {
		return engine;
	}

	public void pauseRender(boolean renderBefore) {
		this.renderThread.pauseRender(renderBefore);		
	}

	public void resumeRender() {
		this.renderThread.resumeRender();		
	}

	public void stopRender() {
		this.renderThread.stopRender();		
	}
	
}
